/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.awpspace.caromini;

/**
 *
 * @author phamk_000
 */
public class Algorithm {

    private BoardCaro caro;
    // xu ly giai thuat   
    private int attack = 0;
    private int defend = 0;  
    public static int ME_TYPE = 2;
    public static int ENEMY_TYPE = 1;
    public int current_me_X;
    public int current_me_Y;
    public int current_enemy_X;
    public int current_enemy_Y;
    // ham danh gia muc do nguy hiem tai 1 vi tri
    private int review_attack[] = new int[]{0, 0, 100, 300, 500, 700, 900, 1000};
    private int review_defend[] = new int[]{0, 0, 99, 299, 499, 699, 899, 999};
        
    private int x_attack, y_attack;
    private int x_defend, y_defend;
    private int stepWin = 5;

    private int[] lineWinner = new int[4];
    public Algorithm() {
        caro = BoardCaro.getInstance();
    }

    private int[] count_row(int x, int y, int type) {
        int left = 0;
        int right = 0;
        if (y - 1 >= 0) {
            for (int i = y - 1; i >= 0; i--) {
                if (caro.getValue(x, i) == type) {
                    left++;
                } else {
                    break;
                }
            }
        }
        if (y + 1 < BoardCaro.COL) {
            for (int i = y + 1; i < BoardCaro.COL; i++) {
                if (caro.getValue(x, i) == type) {
                    right++;
                } else {
                    break;
                }
            }
        }

        return new int[]{left, right};
    }

    // ////////////////////
    private int[] count_column(int x, int y, int type) {
        int left = 0;
        int right = 0;
        if (x - 1 >= 0) {
            for (int i = x - 1; i >= 0; i--) {
                if (caro.getValue(i, y) == type) {
                    left++;
                } else {
                    break;
                }
            }
        }
        if (x + 1 < BoardCaro.ROW) {
            for (int i = x + 1; i < BoardCaro.ROW; i++) {
                if (caro.getValue(i, y) == type) {
                    right++;
                } else {
                    break;
                }
            }
        }

        return new int[]{left, right};
    }

    // //////////////
    private int[] count_diagonal_1(int x, int y, int type) {
        // dem cheo tu trai qua phai
        int left = 0;
        int right = 0;
        int i = x - 1, j = y - 1;
        if (i >= 0 && j >= 0) {
            while (i >= 0 && j >= 0 && caro.getValue(i, j) == type) {
                left++;
                i--;
                j--;
            }
        }
        i = x + 1;
        j = y + 1;
        if (i < BoardCaro.ROW && j < BoardCaro.COL) {
            while (i < BoardCaro.ROW && j < BoardCaro.COL && caro.getValue(i, j) == type) {
                right++;
                i++;
                j++;
            }
        }

        return new int[]{left, right};
    }

    // /
    private int[] count_diagonal_2(int x, int y, int type) {
        int left = 0;
        int right = 0;
        int i = x + 1;
        int j = y - 1;
        if (i < BoardCaro.ROW && j >= 0) {
            while (i < BoardCaro.ROW && j >= 0 && caro.getValue(i, j) == type) {
                left++;
                i++;
                j--;
            }
        }
        i = x - 1;
        j = y + 1;
        if (i >= 0 && j < BoardCaro.COL) {
            while (i >= 0 && j < BoardCaro.COL && caro.getValue(i, j) == type) {
                right++;
                i--;
                j++;
            }
        }
        return new int[]{left, right};
    }

    private void setDefend(int x, int y, int type) {
        int row[] = count_row(x, y, type);
        int col[] = count_column(x, y, type);
        int diagonal_1[] = count_diagonal_1(x, y, type);
        int diagonal_2[] = count_diagonal_2(x, y, type);
        int r = row[0] + row[1];
        int c = col[0] + col[1];
        int d1 = diagonal_1[0] + diagonal_1[1];
        int d2 = diagonal_2[0] + diagonal_2[1];
        int maxx = getMax(r, c, d1, d2);
        int tmp_defend;
        switch (maxx + 1) {
            case 7: {
                tmp_defend = review_defend[7];
            }
            break;
            case 6: {
                tmp_defend = review_defend[6];
            }
            break;
            case 5: {
                tmp_defend = review_defend[5];
            }
            break;
            case 4: {
                tmp_defend = review_defend[4];
            }
            break;
            case 3: {
                tmp_defend = review_defend[3];
            }
            break;
            case 2: {
                tmp_defend = review_defend[2];
            }
            break;

            default: {
                tmp_defend = review_defend[0];
            }
            break;

        }
        if (isEnable(x, y, type)) {
            tmp_defend += 50;
        }
        if (tmp_defend >= defend) {
            defend = tmp_defend;
            x_defend = x;
            y_defend = y;
        }
    }

    private void setAttack(int x, int y, int type) {
        int row[] = count_row(x, y, type);
        int col[] = count_column(x, y, type);
        int diagonal_1[] = count_diagonal_1(x, y, type);
        int diagonal_2[] = count_diagonal_2(x, y, type);
        int r = row[0] + row[1];
        int c = col[0] + col[1];
        int d1 = diagonal_1[0] + diagonal_1[1];
        int d2 = diagonal_2[0] + diagonal_2[1];
        int maxx = getMax(r, c, d1, d2);
        int tmp_attack;
        switch (maxx + 1) {
            case 7: {
                tmp_attack = review_attack[7];
            }
            break;
            case 6: {
                tmp_attack = review_attack[6];
            }
            break;
            case 5: {
                tmp_attack = review_attack[5];
            }
            break;
            case 4: {
                tmp_attack = review_attack[4];
            }
            break;
            case 3: {
                tmp_attack = review_attack[3];
            }
            break;
            case 2: {
                tmp_attack = review_attack[2];
            }
            break;
            default: {
                tmp_attack = review_attack[0];
            }
            break;

        }
        if (isEnable(x, y, type)) {
            tmp_attack += 49;
        }
        if (tmp_attack >= attack) {
            attack = tmp_attack;
            x_attack = x;
            y_attack = y;
        }
    }

    // ham ra quyet dinh dua vao nhung thong so da nhan duoc
    private void research_defend(int key) {
        for (int i = 0; i < BoardCaro.ROW; i++) {
            for (int j = 0; j < BoardCaro.COL; j++) {
                if (caro.getValue(i, j) == 0 && isNonZero(i, j)) {
                    setDefend(i, j, key);
                }
            }
        }
    }

    private void research_Attack(int key) {

        for (int i = 0; i < BoardCaro.ROW; i++) {
            for (int j = 0; j < BoardCaro.COL; j++) {
                if (caro.getValue(i, j) == 0 && isNonZero(i, j)) {
                    setAttack(i, j, key);
                }
            }
        }
    }

    public int getMax(int a, int b, int c, int d) {
        return Math.max(Math.max(a, b), Math.max(c, d));
    }

    public boolean isNonZero(int x, int y) {
        int mV = 2;
        int r = x - 1;
        int r1_count = 0;
        if (r < 0) {
            r1_count = 10;
        }
        while (r >= 0 && (caro.getValue(r, y) == 0)) {
            r--;
            r1_count++;
            if (r < 0 && r1_count < mV) {
                r1_count = 10;
            }
        }

        int r2_count = 0;
        r = x + 1;
        if (r >= BoardCaro.ROW) {
            r2_count = 10;
        }
        while (r < BoardCaro.ROW && (caro.getValue(r, y) == 0)) {
            r++;
            r2_count++;
            if (r >= BoardCaro.ROW && r2_count < mV) {
                r2_count = 10;
            }
        }

        // kiem tra chieu doc
        int c = y - 1;
        int c1_count = 0;
        if (c < 0) {
            c1_count = 10;
        }
        while (c >= 0 && (caro.getValue(x, c) == 0)) {
            c--;
            c1_count++;
            if (c < 0 && c1_count < mV) {
                c1_count = 10;
            }
        }

        c = y + 1;
        int c2_count = 0;
        if (c >= BoardCaro.COL) {
            c2_count = 10;
        }
        while (c < BoardCaro.COL && (caro.getValue(x, c) == 0)) {
            c++;
            c2_count++;
            if (c >= BoardCaro.COL && c2_count < mV) {
                c2_count = 10;
            }
        }

        // kiem tra duoc cheo
        int d1 = x - 1;
        int d2 = y - 1;
        int d1_count = 0;
        if (d1 < 0 || d2 < 0) {
            d1_count = 10;
        }
        while (d1 >= 0 && d2 >= 0 && (caro.getValue(d1, d2) == 0)) {
            d1--;
            d2--;
            d1_count++;
            if ((d1 < 0 || d2 < 0) && d1_count < mV) {
                d1_count = 10;
            }

        }

        d1 = x + 1;
        d2 = y + 1;
        int d2_count = 0;
        if (d1 >= BoardCaro.ROW || d2 >= BoardCaro.COL) {
            d2_count = 10;
        }
        while (d1 < BoardCaro.ROW && d2 < BoardCaro.COL && (caro.getValue(d1, d2) == 0)) {
            d1++;
            d2++;
            d2_count++;
            if ((d1 >= BoardCaro.ROW || d2 >= BoardCaro.COL) && d2_count < mV) {
                d2_count = 10;
            }

        }

        // //
        int d11 = x + 1;
        int d22 = y - 1;
        int d3_count = 0;
        if (d11 >= BoardCaro.ROW || d22 < 0) {
            d3_count = 10;
        }
        while (d11 < BoardCaro.ROW && d22 >= 0 && (caro.getValue(d11, d22) == 0)) {
            d11++;
            d22--;
            d3_count++;
            if ((d11 >= BoardCaro.ROW || d22 < 0) && d3_count < mV) {
                d3_count = 10;
            }
        }

        d11 = x - 1;
        d22 = y + 1;
        int d4_count = 0;
        if (d11 < 0 || d22 >= BoardCaro.COL) {
            d4_count = 10;
        }
        while (d11 >= 0 && d22 < BoardCaro.COL && (caro.getValue(d11, d22) == 0)) {
            d11--;
            d22++;
            d4_count++;
            if ((d11 < 0 || d22 >= BoardCaro.COL) && d4_count < mV) {
                d4_count = 10;
            }
        }
        // 1 duong <= 3 tuc khong phai zero
        // System.out.println(c1_count + " " + c2_count + "  " + r1_count + "  "
        // + r2_count + "  " + d1_count + "  " + d2_count + "  "
        // + d3_count + "  " + d4_count);
        if (c1_count < mV || c2_count < mV || r1_count < mV || r2_count < mV
                || d1_count < mV || d2_count < mV || d3_count < mV || d4_count < mV) {
            return true;
        }
        return false;
    }

    public boolean isEnable(int x, int y, int type) {
        int r = x - 1;
        int r_count = 1;
        boolean isOk = false;
        while (r >= 0
                && (caro.getValue(r, y) == type || caro.getValue(r, y) == 0)) {
            r--;
            r_count++;
            if (r >= 0 && caro.getValue(r, y) == type) {
                isOk = true;
            }
            if (r_count >= stepWin && isOk) {
                return true;
            }
        }
        r = x + 1;
        isOk = false;
        while (r < BoardCaro.ROW
                && (caro.getValue(r, y) == type || caro.getValue(r, y) == 0)) {
            r++;
            r_count++;
            if (r < BoardCaro.ROW && caro.getValue(r, y) == type) {
                isOk = true;
            }
            if (r_count >= 5 && isOk) {
                return true;
            }
        }
        // kiem tra chieu ngang
        int c = y - 1;
        int c_count = 1;
        isOk = false;
        while (c >= 0
                && (caro.getValue(x, c) == type || caro.getValue(x, c) == 0)) {
            c--;
            c_count++;
            if (c >= 0 && caro.getValue(x, c) == type) {
                isOk = true;
            }
            if (c_count >= 5 && isOk) {
                return true;
            }
        }
        c = y + 1;
        isOk = false;
        while (c < BoardCaro.COL
                && (caro.getValue(x, c) == type || caro.getValue(x, c) == 0)) {
            c++;
            c_count++;
            if (c < BoardCaro.COL && caro.getValue(x, c) == type) {
                isOk = true;
            }
            if (c_count >= 5 && isOk) {
                return true;
            }
        }

        // kiem tra duoc cheo
        int d1 = x - 1;
        int d2 = y - 1;
        int d_count = 1;
        isOk = false;
        while (d1 >= 0
                && d2 >= 0
                && (caro.getValue(d1, d2) == type || caro.getValue(d1, d2) == 0)) {
            d1--;
            d2--;
            d_count++;
            if (d1 >= 0 && d2 >= 0 && caro.getValue(d1, d2) == type) {
                isOk = true;
            }
            if (d_count >= 5 && isOk) {
                return true;
            }
        }

        d1 = x + 1;
        d2 = y + 1;
        // d_count = 0;
        isOk = false;
        while (d1 < BoardCaro.ROW
                && d2 < BoardCaro.COL
                && (caro.getValue(d1, d2) == type || caro.getValue(d1, d2) == 0)) {
            d1++;
            d2++;
            d_count++;
            if (d1 < BoardCaro.ROW && d2 < BoardCaro.COL && caro.getValue(d1, d2) == type) {
                isOk = true;
            }
            if (d_count >= 5 && isOk) {
                return true;
            }
        }

        // //
        int d11 = x + 1;
        int d22 = y - 1;
        int d1_count = 1;
        isOk = false;
        while (d11 < BoardCaro.ROW
                && d22 >= 0
                && (caro.getValue(d11, d22) == type || caro.getValue(d11, d22) == 0)) {
            d11++;
            d22--;
            d1_count++;
            if (d11 < BoardCaro.ROW && d22 >= 0 && caro.getValue(d11, d22) == type) {
                isOk = true;
            }
            if (d1_count >= 5 && isOk) {
                return true;
            }
        }

        d11 = x - 1;
        d22 = y + 1;
        // d1_count = 0;
        isOk = false;
        while (d11 >= 0
                && d22 < BoardCaro.COL
                && (caro.getValue(d11, d22) == type || caro.getValue(d11, d22) == 0)) {
            d11--;
            d22++;
            d1_count++;
            if (d11 >= 0 && d22 < BoardCaro.COL && caro.getValue(d11, d22) == type) {
                isOk = true;
            }
            if (d1_count >= 5 && isOk) {
                return true;
            }
        }

        return false;
    }

    public void decision() {
        reset();
        research_Attack(ME_TYPE);
        research_defend(ENEMY_TYPE);
        if (attack == 0 && defend == 0) {
            caro.setValue(4, 5, ME_TYPE);
            current_me_X = 4;
            current_me_Y = 5;
        } else if (attack >= defend) {
            caro.setValue(x_attack, y_attack, ME_TYPE);
            current_me_X = x_attack;
            current_me_Y = y_attack;
        } else {
            caro.setValue(x_defend, y_defend, ME_TYPE);
            current_me_X = x_defend;
            current_me_Y = y_defend;
        }
        System.out.println("Current: " + current_me_X + "  " + current_me_X);
        //return new int[]{current_me_X, current_me_Y};
    }

    public boolean isMeWin(){
        return win(current_me_X, current_me_Y, ME_TYPE);
    }
    public boolean isEnemyWin(){
        return win(current_enemy_X, current_enemy_Y, ENEMY_TYPE);
    }

    public boolean win(int x, int y, int type) {
        int t1[] = count_row(x, y, type);
        int t2[] = count_column(x, y, type);
        int t3[] = count_diagonal_1(x, y, type);
        int t4[] = count_diagonal_2(x, y, type);
        int maxx = getMax(t1[0] + t1[1], t2[0] + t2[1], t3[0] + t3[1], t4[0]
                + t4[1]);
        if (maxx + 1 == 5){             
            return true;
        }
        return false;
        
    }
    
    public void setCurrentEnemy(int x, int y){
        this.current_enemy_X = x;
        this.current_enemy_Y = y;
    }
    public void reset(){
        attack = 0;
        defend = 0;        
    }
}
